package com.example.k8s.hello.service.sys.controller;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.example.k8s.hello.common.exception.ApiExEnum;
import com.example.k8s.hello.service.sys.service.SysCaptchaService;
import com.example.k8s.hello.service.sys.service.SysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
import com.example.k8s.hello.common.annotation.SysLog;
import com.example.k8s.hello.bean.sys.entity.SysUserEntity;
import com.example.k8s.hello.bean.sys.form.SysAppLoginForm;
import com.example.k8s.hello.bean.sys.form.SysLoginForm;
import com.example.k8s.hello.bean.sys.constant.SysConstant;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.time.Duration;
import java.util.Set;

/**
 * 登录相关
 *
 * @author Mark sunlightcs@gmail.com
 */
@Tag(name = "登录相关")
@RestController
@RequiredArgsConstructor
public class SysLoginController{
	private final SysUserService sysUserService;
	private final SysCaptchaService sysCaptchaService;

	@Value("${sa-token.app-timeout:31d}")
	private Duration appTimeout;

	/**
	 * 验证码
	 */
	@Operation(summary = "验证码")
	@GetMapping("captcha.jpg")
	public void captcha(HttpServletResponse response, String uuid)throws IOException {
		response.setHeader("Cache-Control", "no-store, no-cache");
		response.setContentType("image/jpeg");

		//获取图片验证码
		BufferedImage image = sysCaptchaService.getCaptcha(uuid);

		ServletOutputStream out = response.getOutputStream();
		ImageIO.write(image, "jpg", out);
		IOUtils.closeQuietly(out);
	}

	/**
	 * 登录
	 */
	@SysLog(value = "WEB登录", params = false)
	@Operation(summary = "登录")
	@PostMapping("/sys/login")
	public String login(@RequestBody @Validated SysLoginForm form){
		boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
		ApiExEnum.A0007.assertTrue(captcha, "验证码不正确");

		//用户信息
		SysUserEntity user = sysUserService.queryByUserName(form.getUsername());

		if (user == null || !BCrypt.checkpw(form.getPassword(), user.getPassword())) {
			ApiExEnum.A0001.thrown("账号或密码不正确");
		}

		//账号锁定
		if(user.getStatus() == 0){
			ApiExEnum.A0001.thrown("账号或密码不正确");
		}

		StpUtil.login(user.getUserId(), SysConstant.LoginType.WEB.name());

		SaSession session = StpUtil.getSession();

		// 缓存登陆人的信息
		session.set(SaSession.USER, user.buildLoginUser());

		// 缓存登陆人的权限
		Set<String> permissions = sysUserService.getUserPermissions(user.getUserId());
		session.set(SaSession.PERMISSION_LIST, permissions);

		//生成token，并保存到数据库
		return StpUtil.getTokenValue();
	}

	/**
	 * app登录
	 */
	@SysLog(value = "APP登录", params = false)
	@Operation(summary = "app登录")
	@PostMapping("/sys/app-login")
	public String appLogin(@RequestBody @Validated SysAppLoginForm form){
		//用户信息
		SysUserEntity user = sysUserService.queryByUserName(form.getUsername());

		if (user == null || !BCrypt.checkpw(form.getPassword(), user.getPassword())) {
			ApiExEnum.A0001.thrown("账号或密码不正确");
		}

		//账号锁定
		if(user.getStatus() == 0){
			ApiExEnum.A0001.thrown("账号或密码不正确");
		}

		// app端toekn需要更高的过期时间，防止用户频繁登陆
		StpUtil.login(user.getUserId(), new SaLoginModel()
				.setDevice(SysConstant.LoginType.APP.name())
				.setTimeout(appTimeout.getSeconds()));

		SaSession session = StpUtil.getSession();

		// 缓存登陆人的信息
		session.set(SaSession.USER, user.buildLoginUser());

		// 缓存登陆人的权限(只保留和考试,用户相关的权限)
		Set<String> permissions = sysUserService.getUserPermissions(user.getUserId());
		session.set(SaSession.PERMISSION_LIST, permissions);

		//生成token，并保存到数据库
		return StpUtil.getTokenValue();
	}


	/**
	 * 退出
	 */
	@Operation(summary = "退出")
	@PostMapping("/sys/logout")
	public void logout() {
		StpUtil.logout();
	}
	
}
